/*
 * Copyright (c) 2009 Sylvestre Gallon <syl@pmbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#import "xmloader.h"

struct log_hack {
	char *str;
	int value;
};

static const struct log_hack hack[] = {
	{"LOG_ERR", LOG_ERR},
	{"LOG_WARN", LOG_WARN},
	{"LOG_INFO", LOG_INFO},
	{"LOG_DEBUG", LOG_DEBUG},
	{NULL, LOG_DEBUG}
};

static char *
alloc_path(int sizeb, const char *b)
{
	struct passwd *pwd;
	const char *a;
	char *str;
	int sizec;
	int sizea;
	uid_t uid;

	/* XXX Check return value */
	uid = getuid();
	pwd = getpwuid(uid);

	a = pwd->pw_dir;
	sizea = strlen(a);
	sizec = sizea + sizeb;

	str = malloc((sizec + 1) * sizeof(*str));
	memcpy(str, a, sizea);
	memcpy(&(str[sizea]), b, sizeb);
	str[sizec] = '\0';
	
	return str;
}

@implementation xmloader

- (id) init {
	self = [super init];

	if (self) {
		LIBXML_TEST_VERSION

		config_dir = alloc_path(strlen(CONF_DIR), CONF_DIR);
		config_path = alloc_path(strlen(CONF_FILE), CONF_FILE);
		config_log = alloc_path(strlen(CONF_LOG), CONF_LOG);
	}

	return self;
}

- (void) dealloc {
	free(config_path);
	free(config_dir);
	free(config_log);

	xmlCleanupParser();
	xmlMemoryDump();

	[super dealloc];
}

- (int) config_exist {
	if (access(config_path, R_OK) != 0) {
		printf("~/.pb4lol/config.xml does not exist. We create it for you.\n");
		return FALSE;
	}
	return TRUE;
}

- (void) config_create {
	/* XXX Check return value */
	mkdir(config_dir, DEFAULT_DIR_MODE);

	/* Set default value for config */
	[[config instance] set_loglvl: LOG_DEBUG];
	[[config instance] set_logfile: config_log];

	[self save];
}

- (void) load {
	xmlNode *cur;
	char *str;
	int i;

 	doc = xmlReadFile(config_path, NULL, 0);
	if (doc == NULL) {
		/* 
 		 * XXX doc not valid. We need to 
		 * remove this file and recreate it from scratch
		 */
	}
	
	root = xmlDocGetRootElement(doc);

	for (cur = root->children; cur; cur = cur->next) {

		if (xmlStrcmp(cur->name, BAD_CAST "loglvl") == 0) {
			[[config instance] set_loglvl: LOG_DEBUG];
			str = (char *)xmlNodeGetContent(cur);

			for (i = 0; hack[i].str != NULL; i++) {
				if (strncmp(str, hack[i].str, (strlen(str) < strlen(hack[i].str)) ?
					strlen(str) : strlen(hack[i].str)) == 0) {
				  	[[config instance] set_loglvl: hack[i].value];
					break ;
				}
			}	
		}

		if (xmlStrcmp(cur->name, BAD_CAST "logfile") == 0) {
			[[config instance] set_logfile: (char *) xmlNodeGetContent(cur)];
		}
	}
	
	xmlFreeDoc(doc);
}

- (void) save {
	char *dbg;

	doc = xmlNewDoc(BAD_CAST "1.0");
	root = xmlNewNode(NULL, BAD_CAST "root");
	xmlDocSetRootElement(doc, root);

	switch ([[config instance] loglvl]) {
	case LOG_ERR:
		dbg = "LOG_ERR";
		break;
	case LOG_WARN:
		dbg = "LOG_WARN";
		break;
	case LOG_INFO:
		dbg = "LOG_INFO";
		break;
	default:
		dbg = "LOG_DEBUG";
		break;
	}

	xmlNewChild(root, NULL, BAD_CAST "loglvl", 
		BAD_CAST dbg);
	xmlNewChild(root, NULL, BAD_CAST "logfile", 
		BAD_CAST [[config instance] logfile]);

	xmlSaveFile(config_path, doc);
	xmlFreeDoc(doc);
}

@end
